package com.sxpi.order.aop;

import com.sxpi.common.result.R;
import com.sxpi.order.async.MessageAsyncService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @Author: 董伟豪
 * @Date: 2022/10/30 12:10
 */
@Aspect
@Component
@Slf4j
public class MessageAspect {

    /**
     * 这样的做法是比较好的，因为我static只是把他设置为了一个线程池，我就不用在service层继续开辟了
     */
    // public static ThreadLocal<Map<String, Object>> mapMessageThreadLocal = new ThreadLocal<>();

    @Autowired
    private MessageAsyncService messageAsyncService;

    /**
     * 这里我给接口写了一个后置通知，也可以给实现类去写，但是万一以后的子类也要使用
     */
/*
    @After("execution(public * com.sxpi.order.service.order.IOrderService.buyCourse(..))")
    public void afterMessage(){
        log.info("1--------------》下单成功了，开始准备发送消息");
        messageAsyncService.saveOrderMessage(mapMessageThreadLocal.get());
        // 处理完毕一定要remove掉
        mapMessageThreadLocal.remove();
        log.info("2--------------》下单完毕了");
    }
*/

    /**
     * 这个可以拿到异常信息
     * @param ex
     */
    @AfterThrowing(throwing = "ex",pointcut = "execution(public * com.sxpi.order.service.order.IOrderService.buyCourse(..))")
    public void catchMessageService(Throwable ex){
        log.error("消息方法错误"+ex);
    }

    /**
     * 在方法return以后，在方法结束之前
     * 会把结果直接注入进来
     * 就算是这样，我依旧不具有高可用，不看数据库怎么之后消息的成功发送
     * 这里依旧不是完全解耦
     */
    @AfterReturning(returning = "result",pointcut = "execution(public * com.sxpi.order.service.order.IOrderService.buyCourse(..))")
    public void afterReturning(R result){
        log.info("1--------------》下单成功了，开始准备发送消息");
        messageAsyncService.saveOrderMessage(result);
        log.info("2--------------》下单完毕了");
    }
}
